// ***** BEGIN LICENSE BLOCK *****
// Version: MPL 1.1/GPL 2.0/LGPL 2.1
//
// The contents of this file are subject to the Mozilla Public License Version
// 1.1 (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
// http://www.mozilla.org/MPL/
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// The Initial Developer of the Original Code is
//   Axel Nennker http://axel.nennker.de/ .
// Created by the Initial Developer are Copyright (C) 2011
// the Initial Developer. All Rights Reserved.

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;

Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");

function log(aMessage) {
//Services.console.logStringMessage("openid_storage: " + aMessage);
}

function OpenIdStorage() {
  this.wrappedJSObject = this;
  this.passwordManager = Components.classes["@mozilla.org/login-manager;1"].
    getService(Components.interfaces.nsILoginManager);
  this.nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
      Components.interfaces.nsILoginInfo,
      "init");
}
  
OpenIdStorage.prototype = {
  classDescription: "Component to store openids",
  classID:          Components.ID("{3cb415b0-5922-11e0-80e3-0800200c9a66}"),
  contractID:       "@openinfocard.com/openidstorage;1",
  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports]),

  addOpenID : function _addOpenID(realm, claimed_id, identity, op_endpoint) {
    var obj = {};
    var host = realm;
    var user = claimed_id;
    var data = {"identity" : identity, "op_endpoint" : op_endpoint};
    var password = JSON.stringify(data);
    log("addOpenID realm=" + realm + " claimed_id=" + claimed_id);
    var formLoginInfo = new this.nsLoginInfo(host,
        'chrome://openidnascar/store', null,
        user, password, 
        'uname', 'pword');
    this.passwordManager.addLogin(formLoginInfo);
  },

  updateInputfield: function _updateInputfield(realm, claimed_id, inputfield)
  {
    if (!realm) {
      log("_updateInputfield !realm claimed_id" + claimed_id);
      var allLogins = this.passwordManager.getAllLogins({});
      for (var i=0; i<allLogins.length;i++) {
        var login = allLogins[i];
        if (login.formSubmitURL == 'chrome://openidnascar/store') {
          log("_updateInputfield !realm login.username=" + login.username);
          if (login.username == claimed_id) {
            var newLogin = login.clone();
            newLogin.usernameField = inputfield;
            this.passwordManager.modifyLogin(login, newLogin);
            return true;
          }
        }
      }
    } else {
      log("isOpenIdInStore realm claimed_id" + claimed_id);
      var logins = this.findOpenIds(realm);
      for (var i=0; i<logins.length; i++) {
        var login = logins[i];
        log("_updateInputfield realm login.username" + login.username);
        if (login.username == claimed_id) {
          var newLogin = login.clone();
          newLogin.usernameField = inputfield;
          this.passwordManager.modifyLogin(login, newLogin);
          return true;
        }
      }
    }
    return false;
  },

deleteAllOpenIDs: function _deleteAllOpenIDs()
{
  log("deleteAllOpenIDs");
  var httprealm = null;
  var logins = this.passwordManager.findLogins(
      {}, 
      "", // matches any realm 
      'chrome://openidnascar/store', 
      httprealm);
  for (var i=0; i<logins.length; i++) {
    var login = logins[i];
    log("deleteAllOpenIDs login.username=" + login.username);
    this.passwordManager.removeLogin(login);
  }
},

deleteOpenID: function _deleteOpenID(realm, claimed_id)
{
    log("deleteOpenID claimed_id=" + claimed_id + " realm=" + realm);
    var httprealm = null;
    var logins = this.passwordManager.findLogins(
        {}, 
        realm, 
        'chrome://openidnascar/store', 
        httprealm);
    for (var i=0; i<logins.length; i++) {
      var login = logins[i];
      if (claimed_id) {
        if (login.username == claimed_id) {
          log("deleteOpenID removing claimed_id=" + claimed_id + " realm=" + realm);
          this.passwordManager.removeLogin(login);
        }
      } else {
        log("deleteOpenID removing username=" + login.username + " realm=" + realm);
        this.passwordManager.removeLogin(login);
      }
    }
  },

  getPreferredOpenIdLogin : function _getPreferredOpenIdLogin() {
    var logins = this.findOpenIds('chrome://openidnascar/preferred');
    if (logins.length >1) {
      log("unsetPreferredOpenID internal error: logins.length>1 : " + logins.length);
      // continue
    }
    if (logins.length == 0) {
      return null;
    }
    return logins[0];
  },

  getPreferredOpenID : function _getPreferredOpenID() {
    var login = this.getPreferredOpenIdLogin();
    if (login) {
      return login.username; // claimed_id
    } else {
      return null;
    }
  },

  setPreferredOpenID : function _setPreferredOpenID(claimed_id, identity, op_endpoint) {
    log("setPreferredOpenID claimed_id : " + claimed_id);
    this.unsetPreferredOpenID();
    this.addOpenID('chrome://openidnascar/preferred', claimed_id, identity, op_endpoint);
  },

  unsetPreferredOpenID : function _unsetPreferredOpenID() {
    var logins = this.findOpenIds('chrome://openidnascar/preferred');
    if (logins.length >1) {
      log("unsetPreferredOpenID internal error: logins.length>1 : " + logins.length);
      // continue
    }
    for (var i=0; i<logins.length; i++) {
      var login = logins[i];
      log("unsetPreferredOpenID login.username=" + login.username + " login.password=" + login.password);
      this.passwordManager.removeLogin(login);
    }
  },

  findOpenIds: function _findOpenIds(realm) {
    var logins = [];
//    log("findLogins realm=" + realm);
    var httprealm = null;
    var logins = this.passwordManager.findLogins(
        {}, 
        realm, 
        'chrome://openidnascar/store', 
        httprealm);
//    log("findLogins logins.length=" + logins.length);
    for (var i=0; i<logins.length;i++) {
      var login = logins[i];
//      log("findLogins login.username=" + login.username);
    }
    return logins;
  }, 
  
  getAllOpenIDs: function() {
    var logins = [];
    var allLogins = this.passwordManager.getAllLogins({});
    for (var i=0; i<allLogins.length;i++) {
      var login = allLogins[i];
      if (login.hostname != 'chrome://openidnascar/preferred') {
        if (login.formSubmitURL == 'chrome://openidnascar/store') {
          logins.push(login);
        }
      }
    }
    return logins;
  }, 
  
  setOpenIDName : function _setOpenIDName(claimed_id, realm, openidname) {
	  try {
	      var logins = this.findOpenIds(realm);
	      for (var i=0; i<logins.length; i++) {
	        var login = logins[i];
	        log("setOpenIDName realm login.username" + login.username);
	        if (login.username == claimed_id) {
	            log("setOpenIDName realm login.username" + login.username + " openidname=" + openidname);
	            var passwordStr = login.password;
	            var data = JSON.parse(passwordStr);
	            data.openidname = openidname;
	            var host = realm;
	            var user = claimed_id;
	            var password = JSON.stringify(data);
	            var newLogin = new this.nsLoginInfo(host,
	                    'chrome://openidnascar/store', null,
	                    user, password, 
	                    'uname', 'pword');
	            this.passwordManager.modifyLogin(login, newLogin);
	            return;
	        }
	      }
	  } catch(e) {
	    Cu.reportError(e);
	  }
  },
  
  getOpenIDName: function _getOpenIDName(claimed_id, realm) {
	  if (realm) {
	      var logins = this.findOpenIds(realm);
	      for (var i=0; i<logins.length; i++) {
	        var login = logins[i];
	        log("getOpenIDName realm login.username=" + login.username + " claimed_id="+claimed_id + " realm="+realm);
	        if (login.username == claimed_id) {
	            var passwordStr = login.password;
	            var data = JSON.parse(passwordStr);
	            if (data.openidname) {
  	            log("getOpenIDName realm login.username" + login.username + " openidname=" + data.openidname);
  	            return data.openidname;
	            } else {
	              // this openid does not have an user-set name
	              log("getOpenIDName realm login.username" + login.username + " openidname=not set");
	              return null;
	            }
	        }
	      }
	  } else {
	      log("getOpenIDName !realm claimed_id" + claimed_id);
	      var allLogins = this.passwordManager.getAllLogins({});
	      for (var i=0; i<allLogins.length;i++) {
	        var login = allLogins[i];
	        if (login.formSubmitURL == 'chrome://openidnascar/store') {
	          log("isOpenIdInStore !realm login.username=" + login.username);
	          if (login.username == claimed_id) {
	            var passwordStr = login.password;
	            var data = JSON.parse(passwordStr);
	            if (data.openidname) {
  	            log("getOpenIDName !realm login.username" + login.username + " openidname=" + data.openidname);
  	            return data.openidname;
	            } else {
	              log("getOpenIDName !realm login.username" + login.username + " openidname=Not set");
                return null;	            }
	          }
	        }
	      }
	  }
      return null;
  }, 
  
  getImage: function _getImage(claimed_id, realm) {
	  if (realm) {
	      var logins = this.findOpenIds(realm);
	      for (var i=0; i<logins.length; i++) {
	        var login = logins[i];
	        log("getImage realm login.username=" + login.username + " claimed_id="+claimed_id + " realm="+realm);
	        if (login.username == claimed_id) {
	            var passwordStr = login.password;
	            var data = JSON.parse(passwordStr);
	            if (data.dataUrl) {
  	            log("getImage realm login.username" + login.username + " dataUrl=" + data.dataUrl);
  	            return data.dataUrl;
	            } else {
	              // default openid icon is used to depict this openid
	              log("getImage realm login.username" + login.username + " dataUrl=Not set");
	              return null;
	            }
	        }
	      }
	  } else {
	      log("getImage !realm claimed_id" + claimed_id);
	      var allLogins = this.passwordManager.getAllLogins({});
	      for (var i=0; i<allLogins.length;i++) {
	        var login = allLogins[i];
	        if (login.formSubmitURL == 'chrome://openidnascar/store') {
	          log("isOpenIdInStore !realm login.username=" + login.username);
	          if (login.username == claimed_id) {
	            var passwordStr = login.password;
	            var data = JSON.parse(passwordStr);
	            if (data.dataUrl) {
  	            log("getImage !realm login.username" + login.username + " dataUrl=" + data.dataUrl);
  	            return data.dataUrl;
	            } else {
	              log("getImage !realm login.username" + login.username + " dataUrl=not set");
                return null;	            
              }
	          }
	        }
	      }
	  }
      return null;
  }, 
  
  setImage: function _setImage(claimed_id, realm, dataUrl) {
	  try {
	      var logins = this.findOpenIds(realm);
	      for (var i=0; i<logins.length; i++) {
	        var login = logins[i];
	        log("setImage realm login.username" + login.username);
	        if (login.username == claimed_id) {
	            log("setImage realm login.username" + login.username + " dataUrl=" + dataUrl);
	            var passwordStr = login.password;
	            var data = JSON.parse(passwordStr);
	            data.dataUrl = dataUrl;
	            var host = realm;
	            var user = claimed_id;
	            var password = JSON.stringify(data);
	            var newLogin = new this.nsLoginInfo(host,
	                    'chrome://openidnascar/store', null,
	                    user, password, 
	                    'uname', 'pword');
	            this.passwordManager.modifyLogin(login, newLogin);
	            return;
	        }
	      }
	  } catch(e) {
	    Cu.reportError(e);
	  }
  }, 
  
  isOpenIdInStore: function _isOpenIdInStore(claimed_id, realm) {
    if (!realm) {
      log("isOpenIdInStore !realm claimed_id" + claimed_id);
      var allLogins = this.passwordManager.getAllLogins({});
      for (var i=0; i<allLogins.length;i++) {
        var login = allLogins[i];
        if (login.formSubmitURL == 'chrome://openidnascar/store') {
          log("isOpenIdInStore !realm login.username=" + login.username);
          if (login.username == claimed_id) {
            return true;
          }
        }
      }
    } else {
      log("isOpenIdInStore realm claimed_id" + claimed_id);
      var logins = this.findOpenIds(realm);
      for (var i=0; i<logins.length; i++) {
        var login = logins[i];
        log("isOpenIdInStore realm login.username" + login.username);
        if (login.username == claimed_id) {
          return true;
        }
      }
    }
    return false;
  }
};

var NSGetFactory = XPCOMUtils.generateNSGetFactory([OpenIdStorage]);
